using System;
using System.DHTML;
using Ext;
using Ext.data;
using Ext.form;
using Ext.grid;
using Ext.util;
using ScriptFX;

namespace SampleScripts.grid {
    public delegate void MouseDownDelegate(EventObject e, DOMElement t);

    public class EditGridScript {
        public static void main(Dictionary args) {
            ExtClass.onReady(new AnonymousDelegate(delegate() { new EditGridScript().init(); }));
        }

        public void init() {
            CheckColumn checkCol = new CheckColumn(new ColumnModelConfig()
                .header("Indoor?")
                .dataIndex("indoor")
                .width(55)
                .ToDictionary()
            );

            ColumnModel cm = new ColumnModel(new object[] {
                new ColumnModelConfig()
                    .id("common")
                    .header("Common Name")
                    .dataIndex("common")
                    .width(220)
                    .editor(new TextField(new TextFieldConfig().allowBlank(false).ToDictionary()))
                    .ToDictionary(),
                new ColumnModelConfig()
                    .header("Light")
                    .dataIndex("light")
                    .width(130)
                    .editor(new ComboBox(new ComboBoxConfig()
                        .typeAhead(true)
                        .triggerAction("all")
                        .transform("light")
                        .lazyRender(true)
                        .listClass("x-combo-list-small")
                        .ToDictionary()
                    ))
                    .ToDictionary(),
                new ColumnModelConfig()
                    .header("Price")
                    .dataIndex("price")
                    .width(70)
                    .align("right")
                    .renderer(new MoneyRenderer(Format.usMoney))
                    .editor(new NumberField(new NumberFieldConfig()
                        .allowBlank(false)
                        .allowNegative(false)
                        .maxValue(100000)
                        .ToDictionary()
                    ))
                    .ToDictionary(),
                new ColumnModelConfig()
                    .header("Available")
                    .dataIndex("availDate")
                    .width(95)
                    .renderer(new ColumnRenderer(formatDate))
                    .editor(new DateField(new DateFieldConfig()
                        .format("m/d/y")
                        .minValue("01/01/06")
                        .disabledDays(new int[] {0,6})
                        .disabledDaysText("Plants are not available on the weekends")
                        .ToDictionary()
                    ))
                    .ToDictionary(),
                checkCol
            });

            // by default columns are sortable
            cm.defaultSortable = true;

            // Record.create cannot be used because c# does not allow you to
            // dynamically create types that can be instanciated
            // so we will just create the dictionary reference that can be reused
            Dictionary[] plantDef = new Dictionary[] {
                new Dictionary("name", "common", "type", "string"),
                new Dictionary("name", "botanical", "type", "string"),
                new Dictionary("name", "light"),
                new Dictionary("name", "price", "type", "float"), // automatic date conversions
                new Dictionary("name", "availDate", "mapping", "availability", "type", "date", "dateFormat", "m/d/Y"),
                new Dictionary("name", "indoor", "type", "bool")
            };

            Store ds = new Store(new StoreConfig()
                // load using HTTP
                .url("plants.xml")

                // the return will be XML, so lets set up a reader
                .reader(new XmlReader(
                    new XmlReaderConfig()
                        // records will have a "plant" tag
                        .record("plant")
                        .ToDictionary(),
                        plantDef
                 ))
                 .sortInfo(new Dictionary("field", "common", "direction", "ASC"))
                 .ToDictionary()
            );

            // create the editor grid
            EditorGridPanel grid = null;
            grid = new EditorGridPanel(new EditorGridPanelConfig()
                .ds(ds)
                .cm(cm)
                .renderTo("editor-grid")
                .width(600)
                .height(300)
                .autoExpandColumn("common")
                .title("Edit Plants?")
                .frame(true)
                .plugins(checkCol)
                .clicksToEdit(1)
                .tbar(new Dictionary[] {
                    new Dictionary(
                        "text", "Add Plant",
                        "handler",  new Callback(delegate() {
                            Record p = new Record(plantDef);
                            grid.stopEditing();
                            ds.insert(0, new Record[] { p });
                            p.set("common", "New Plant 1");
                            p.set("light", "Mostly Shade");
                            p.set("price", 0);
                            p.set("availDate", new Date());
                            p.set("indoor", false);
                            grid.startEditing(0, 0);                            
                        })
                    ) 
                })
                .ToDictionary()
            );

            // trigger the data store load
            ds.load();
        }

        public object formatBoolean(object value) {
            return (bool)value ? "Yes" : "No";
        }

        public object formatDate(object value) {
            return Script.IsNullOrUndefined(value) ? "" : Type.InvokeMethod(value, "dateFormat", "M d, Y");
        }
    }

    public class CheckColumn {
        public string id = null;
        public string dataIndex = null;
        public Ext.grid.GridPanel grid;

        public CheckColumn(Dictionary config) {
            ExtClass.apply(this, config, null);
            if (Script.IsNullOrUndefined(this.id)) {
                this.id = ExtClass.id();
            }
        }

        public void init(Ext.grid.GridPanel g) {
            this.grid = g;
            this.grid.on("render", new AnonymousDelegate(delegate() {
                GridView view = this.grid.getView();
                Element el = (Element)Type.GetField(view, "mainBody");
                el.on("mousedown", new MouseDownDelegate(this.onMouseDown), this);
            }), this);
        }

        public void onMouseDown(EventObject e, DOMElement t) {
            if (!Script.IsNullOrUndefined(t.ClassName) && t.ClassName.IndexOf("x-grid3-cc-" + this.id) != -1) {
                e.stopEvent();
                int index = (int)Type.InvokeMethod(this.grid.getView(), "findRowIndex", t);
                Record record = this.grid.store.getAt(index);
                bool val = (bool)record.get(this.dataIndex);
                record.set(this.dataIndex, !val);
            }    
        }

        public object renderer(object value, Dictionary p, Record record) {
            p["css"] += " x-grid3-check-col-td";
            return "<div class=\"x-grid3-check-col" + ((bool)value ? "-on" : "") + " x-grid3-cc-" + this.id + "\">&#160;</div>";
        }
    }
}
